<?php

namespace app\resources\model;

use help\EncryptionHelp;
use app\resources\model\WebSocket;
use app\resources\service\OldcService;

class Nodes extends BaseModel
{
    const FRPS_DIRECTORY = '/usr/frps/config';    //fros 目录
    const MIN_PROT = 40000;     // 容器最小端口
    const MAX_PROT = 60000;     // 容器最大端口
   
    // 写入后
    public static function onAfterWrite($data)
    {
        WebSocket::pushAllUser([ 'type' => 'update', 'body' => $data ]);
    }

    // 一对多关联
    public function frps()
    {
    	return $this->hasMany(NodesFrps::class,'nid');
    }

    // 一对多关联
    public function prots()
    {
    	return $this->hasMany(NodesPort::class,'nid');
    }
    
    /**
     * 获取密钥
     * @return void
     */
    public static function getSecretKey(){
        return EncryptionHelp::encryptString( EncryptionHelp::makeEncrypt() ,'node');
    }

    /**
     * 解密密钥
     * @return void
     */
    public static function decryptSecretKey($encrypt){
        return EncryptionHelp::decryptString($encrypt,'node');
    }

    /**
     * 获取端口
     * @return void
     */
    public function getProt(){
        $prots = $this->prots()->column('port');
        for ($i=self::MIN_PROT; $i < self::MAX_PROT; $i++) { 
            if(!in_array($i,$prots)){
                return $i;
            }
        }
        throw new \think\Exception('暂无可用端口！');
    }

    /**
     * 获取cmd
     * @return void
     */
    public function getCmd(){
        $parentDir = self::FRPS_DIRECTORY;
        $issuer = OldcService::getRouteOidcIssuer();
        // 初始化目录
        $cmds[] = <<<EOG
            #!/bin/sh

            #创建目录
            if [ ! -d "$parentDir" ]; then
                mkdir -p $parentDir
            fi
            EOG;
        // 删除并停止所有fprs
        $cmds[] = <<<EOG
            # 删除所有配置文件
            rm  -rf $parentDir/*
            # 停止所有fprs
            for line in $(ps aux | grep frp | grep config | grep -v grep | awk '{print $2}')
            do
            kill -9 \$line
            done
            EOG;    
        // 构建所有frps配置    
        foreach($this->frps as $frps){
            $fileName= $frps->id.'-'.$frps->bind_port.'.ini';
            $dirAndName = $parentDir.'/'.$fileName;
            $cmds[] = <<<EOG
            #创建配置文件-并添加内容
            cd $parentDir 
            cat>$dirAndName<<-EOF
            [common]
            bind_port = $frps->bind_port
            vhost_http_port = $frps->vhost_http_port
            vhost_https_port = $frps->vhost_https_port
            detailed_errors_to_client = false
            # auth
            authentication_method = oidc #token和oidc，默认为 token
            authenticate_new_work_conns = true
            oidc_issuer = $issuer
            oidc_audience = $frps->token
            # 自定义域名 在frpc的代理中可以不配置custom_domains 而是配置一个subdomain参数。
            subdomain_host = $frps->subdomain_host
            # 开放端口
            privilege_allow_ports = $frps->privilege_allow_ports
            # 最大连接数
            max_pool_count = $frps->max_pool_count
            # 这个是frp内网穿透服务器的web界面的端口和账号密码
            dashboard_port = $frps->dashboard_port
            dashboard_user = $frps->dashboard_user
            dashboard_pwd = $frps->dashboard_pwd
            # 日志 - 日志的记录级别，分为debug, info, warn, error四级，日志保存的天数，默认3天
            log_file = ./frps.log
            log_level = info
            log_max_days = 3
            EOF
            EOG;
        }
        // 启动
        $cmds[] = <<<EOG
            # 启动所有进程
            for file in /usr/frps/config/*
            do
            if [ $(echo \$file | grep '.ini') ]; then
                nohup /usr/frps/frps -c \$file >/dev/null 2>&1 &
            fi
            done
            EOG;
        // 成功
        $cmds[] = <<<EOG
            echo success
            EOG;    
        //   
        return implode("\n\n", $cmds);
    }
    
}